const $parameters = {
    btnID: 'openBtn',
    panelID: 'colorPickerPanel',
    quickColorsContainerID: 'quickColorsContainer',
    mainColorID: 'mainColor',
    selectorID: 'selector',
    colorBarID: 'colorBar',
    colorSliderID: 'colorSlider',
    alphaBarID: 'alphaBar',
    alphaSliderID: 'alphaSlider',
    resultPreviewID: 'resultPreview',
    colorTypeSelectID: 'colorTypeSelect',
    hexContainerID: 'hexContainer',
    rgbContainerID: 'rgbContainer',
    hexInputID: 'hexInput',
    RInputID: 'RInput',
    GInputID: 'GInput',
    BInputID: 'BInput',
    opacityInputID: 'opacityInput',

    quickColors: ['#ffffff'/*占位*/, '#4C4C4C', '#989898', '#FEFEFE', '#F34D3A', '#FD9100', '#FBDB00', '#DADE00', '#A3DC02', '#67CBC9', '#71D7FE',
        '#AD9FFE', '#FC9FFE',
        '#ffffff'/*占位*/, '#4C4C4C', '#989898', '#FEFEFE', '#F34D3A', '#FD9100', '#FBDB00', '#DADE00', '#A3DC02', '#67CBC9', '#71D7FE',
        '#AD9FFE', '#FC9FFE',
        '#ffffff'/*占位*/, '#4C4C4C', '#989898', '#FEFEFE', '#F34D3A', '#FD9100', '#FBDB00', '#DADE00', '#A3DC02', '#67CBC9', '#71D7FE',
        '#AD9FFE', '#FC9FFE'],
}

const btnDOM = document.querySelector('#' + $parameters.btnID) // 按钮
const panelDOM = document.querySelector('#' + $parameters.panelID) // 面板
const quickColorsContainerDOM = document.querySelector('#' + $parameters.quickColorsContainerID) // 面板内快速选择颜色容器
const mainColorDOM = document.querySelector('#' + $parameters.mainColorID) // 面板内颜色选择色调色
const selectorDOM = document.querySelector('#' + $parameters.selectorID) // 面板内颜色选择器

const colorBarDOM = document.querySelector('#' + $parameters.colorBarID) // 面板内右侧colorBar
const colorSliderDOM = document.querySelector('#' + $parameters.colorSliderID) // 面板内右侧color滑块

const alphaBarDOM = document.querySelector('#' + $parameters.alphaBarID) // 面板内右侧alphaBar
const alphaSliderDOM = document.querySelector('#' + $parameters.alphaSliderID) // 面板内右侧alpha滑块

const resultPreviewDOM = document.querySelector('#' + $parameters.resultPreviewID) // 面板内右侧预览模块

const colorTypeSelectDOM = document.querySelector('#' + $parameters.colorTypeSelectID) // 面板内底部select

const hexInputDOM = document.querySelector('#' + $parameters.hexInputID) // 面板内底部hex
const RInputDOM = document.querySelector('#' + $parameters.RInputID) // 面板内底部r
const GInputDOM = document.querySelector('#' + $parameters.GInputID) // 面板内底部g
const BInputDOM = document.querySelector('#' + $parameters.BInputID) // 面板内底部b
const opacityInputDOM = document.querySelector('#' + $parameters.opacityInputID) // 面板内底部opacity

const hexContainerDOM = document.querySelector('#' + $parameters.hexContainerID) // 面板内HEX
const rgbContainerDOM = document.querySelector('#' + $parameters.rgbContainerID) // 面板内RGB

const currentColor = {
    hsv: [0, 0, 100], // 色度：x / width * 360； 饱和度：x / width； 明度：1 - y / height
    rgb: [255, 255, 255],
    opacity: 1,
    hex: '#ffffff'
}

// 生成快捷颜色节点
{
    console.log('生成快捷颜色节点')
    const container = document.createDocumentFragment()
    $parameters.quickColors.forEach((color) => {
        const node = document.createElement('div')
        node.classList.add('quickColorNode')
        node.style.backgroundColor = color
        container.appendChild(node)
    })
    quickColorsContainerDOM.appendChild(container)
}

// EventListener
{
    // 打开调色器
    btnDOM.addEventListener('click', (event) => {
        event.stopPropagation()
        panelDOM.style.left = btnDOM.offsetLeft + 'px'
        panelDOM.style.top = btnDOM.offsetTop + btnDOM.offsetHeight + 10 + 'px'
        panelDOM.style.display = 'inline-block'
    })

    // 调色器面板点击
    panelDOM.addEventListener('click', (event) => {
        event.stopPropagation()
    })

    quickColorsContainerDOM.addEventListener('click', (event) => {
        if (event.target.className.indexOf('quickColorNode') !== -1) {
            console.log(event.target.style.backgroundColor);
            setColor(event.target.style.backgroundColor)
            setOpacity(1)
        }
    })

    colorTypeSelectDOM.addEventListener('change', (event) => {
        const colorType = colorTypeSelectDOM.options[colorTypeSelectDOM.selectedIndex].value
        hexContainerDOM.style.display = colorType === 'hex' ? 'block' : 'none'
        rgbContainerDOM.style.display = colorType === 'rgb' ? 'flex' : 'none'
    })

    hexInputDOM.addEventListener('keyup', (event) => {
        setColor(hexInputDOM.value)
    })

    const RGBevent = (DOM) => {
        if (DOM.value != parseInt(DOM.value)) DOM.value = '0'
        if (DOM.value > 255) DOM.value = '255'
        if (DOM.value < 0) DOM.value = '0'
        setColor(`rgb(${getPageRGB()})`)
    }

    RInputDOM.addEventListener('keyup', () => RGBevent(RInputDOM))
    GInputDOM.addEventListener('keyup', () => RGBevent(GInputDOM))
    BInputDOM.addEventListener('keyup', () => RGBevent(BInputDOM))

    opacityInputDOM.addEventListener('keyup', (event) => {
        setOpacity(opacityInputDOM.value / 100)
    })

    // 关闭调色器点击
    document.addEventListener('click', (event) => {
        panelDOM.style.display = 'none'
    })
}

const getPageRGB = () => {
    return [Number(RInputDOM.value), Number(GInputDOM.value), Number(BInputDOM.value)]
}


// 16进制以及rgb正则
const hexReg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
const rgbReg = /^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/gi;

// 设置颜色
const setColor = (inColor) => {
    console.log(inColor, hexReg.test(inColor), rgbReg.test(inColor));
    let color = inColor
    let hsv = []
    let isHex = false
    // 16进制 #ffffff
    if (hexReg.test(color)) {
        isHex = true
        currentColor.hex = color
        hexInputDOM.value = currentColor.hex
        color = hex2rgb(color)
    }

    console.log(color);
    if (rgbReg.test(color)) { // rgb(1,1,1)
        if (!isHex) {
            currentColor.hex = rgb2hex(color)
            hexInputDOM.value = currentColor.hex
        }
        currentColor.rgb = color.replace(/\(|\)|rgb|rgba| /gi, '').split(',')
        for (let i = 0; i < currentColor.rgb.length; i++) {
            currentColor.rgb[i] = Number(currentColor.rgb[i])
        }
        RInputDOM.value = currentColor.rgb[0]
        GInputDOM.value = currentColor.rgb[1]
        BInputDOM.value = currentColor.rgb[2]
        hsv = rgb2hsv(...currentColor.rgb)

        const H = hsv[0] * colorBarDOM.clientWidth / 360 - 3
        const S = hsv[1] * mainColorDOM.clientWidth - 4
        const V = (1 - hsv[2]) * mainColorDOM.clientHeight - 4
        setHsv(H, S, V)
        setStyle()
    }
}

// 设置透明度
const setOpacity = (inOpacity) => {
    let opacity = 1
    if (inOpacity == Number(inOpacity)) {
        opacity = inOpacity
        if (inOpacity < 0) opacity = 0
        if (inOpacity > 1) opacity = 1
    }
    currentColor.opacity = opacity
    alphaSliderDOM.style.left = (currentColor.opacity * alphaBarDOM.clientWidth - 3).toFixed(0) + 'px'
    opacityInputDOM.value = (currentColor.opacity * 100).toFixed(0)
    resultPreviewDOM.style.background = `rgba(${currentColor.rgb},${currentColor.opacity})`
}

/** 
* @function 设置hsv
* @param H {number} 坐标
* @param S {number} 坐标
* @param V {number} 坐标
*/
const setHsv = (H, S, V) => {
    console.log('setHsv');
    if (H !== undefined) {
        colorSliderDOM.style.left = H + 'px'
        currentColor.hsv[0] = ((H + 3) / colorBarDOM.clientWidth * 360).toFixed(0)
    }
    if (S !== undefined) {
        selectorDOM.style.left = S + 'px'
        currentColor.hsv[1] = ((S + 4) / mainColorDOM.clientWidth) * 100
    }
    if (V !== undefined) {
        selectorDOM.style.top = V + 'px'
        currentColor.hsv[2] = (1 - (V + 4) / mainColorDOM.clientHeight) * 100
    }
}

/** 
* @function 使用hsv设置16进制以及rgb
*/
const setResultByHsv = () => {
    currentColor.rgb = hsv2rgb(Number(currentColor.hsv[0]), Number(currentColor.hsv[1]), Number(currentColor.hsv[2]))
    RInputDOM.value = currentColor.rgb[0]
    GInputDOM.value = currentColor.rgb[1]
    BInputDOM.value = currentColor.rgb[2]

    currentColor.hex = rgb2hex(`rgb(${currentColor.rgb})`)
    hexInputDOM.value = currentColor.hex
}

const setStyle = () => {
    mainColorDOM.style.background = `linear-gradient(to left, hsla(${currentColor.hsv[0]}, 100%, 50%, 1), rgba(255, 255, 255, 1))`
    resultPreviewDOM.style.background = `rgba(${currentColor.rgb},${currentColor.opacity})`
    alphaBarDOM.style.backgroundImage = `linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgb(${currentColor.rgb}) 100%)`
}

// 中间颜色选择滑动
{
    let orgClientX = 0
    let orgClientY = 0
    let orgLayerX = 0
    let orgLayerY = 0
    const selector = (event) => {
        const diffX = event.clientX - orgClientX
        let X = orgLayerX + diffX
        if (X < -4) X = -4
        if (X > mainColorDOM.clientWidth - 4) X = mainColorDOM.clientWidth - 4

        const diffY = event.clientY - orgClientY
        let Y = orgLayerY + diffY
        if (Y < -4) Y = -4
        if (Y > mainColorDOM.clientHeight - 4) Y = mainColorDOM.clientHeight - 4

        setHsv(undefined, X, Y)
        setResultByHsv()
        setStyle()
    }

    mainColorDOM.addEventListener('mousedown', (event) => {
        orgClientX = event.clientX
        orgClientY = event.clientY
        orgLayerX = event.layerX
        orgLayerY = event.layerY
        selectorDOM.style.top = event.layerY + 'px'
        selectorDOM.style.left = event.layerX + 'px'

        selector(event)
        document.addEventListener('mousemove', selector)
    })

    document.addEventListener('mouseup', (event) => {
        document.removeEventListener('mousemove', selector)
    })
}

// 下方colorSlider滑动
{
    let orgClientX = 0
    let orgLayerX = 0
    const slither = (event) => {
        const diff = event.clientX - orgClientX
        let X = orgLayerX + diff
        if (X < -3) X = -3
        if (X > colorBarDOM.clientWidth - 4) X = colorBarDOM.clientWidth - 4
        setHsv(X)
        setResultByHsv()
        setStyle()
    }

    colorBarDOM.addEventListener('mousedown', (event) => {
        orgClientX = event.clientX
        orgLayerX = event.layerX
        colorSliderDOM.style.left = event.layerX + 'px'

        slither(event)
        document.addEventListener('mousemove', slither)
    })

    document.addEventListener('mouseup', (event) => {
        document.removeEventListener('mousemove', slither)
    })
}

// 下方alphaSlider滑动
{
    let orgClientX = 0
    let orgLayerX = 0
    const slither = (event) => {
        const diff = event.clientX - orgClientX
        let X = orgLayerX + diff
        if (X < -3) X = -3
        if (X > alphaBarDOM.clientWidth - 3) X = alphaBarDOM.clientWidth - 3
        alphaSliderDOM.style.left = X + 'px'
        const opacity = ((X + 3) / alphaBarDOM.clientWidth).toFixed(2)
        setOpacity(opacity)
    }

    alphaBarDOM.addEventListener('mousedown', (event) => {
        orgClientX = event.clientX
        orgLayerX = event.layerX
        alphaSliderDOM.style.left = event.layerX + 'px'

        slither(event)
        document.addEventListener('mousemove', slither)
    })

    document.addEventListener('mouseup', (event) => {
        document.removeEventListener('mousemove', slither)
    })
}

// 初始化
setTimeout(() => {
    setColor('#ffffff')
    setOpacity(0.5)
}, 1000);

const hsv2rgb = (h, s, v) => {
    s = s / 100;
    v = v / 100;
    var h1 = Math.floor(h / 60) % 6;
    var f = h / 60 - h1;
    var p = v * (1 - s);
    var q = v * (1 - f * s);
    var t = v * (1 - (1 - f) * s);
    var r, g, b;
    switch (h1) {
        case 0:
            r = v;
            g = t;
            b = p;
            break;
        case 1:
            r = q;
            g = v;
            b = p;
            break;
        case 2:
            r = p;
            g = v;
            b = t;
            break;
        case 3:
            r = p;
            g = q;
            b = v;
            break;
        case 4:
            r = t;
            g = p;
            b = v;
            break;
        case 5:
            r = v;
            g = p;
            b = q;
            break;
    }
    return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
}

const rgb2hsv = (r1, r2, r3) => {
    const maxJ = Math.max(r1, r2, r3)
    const minJ = Math.min(r1, r2, r3)
    const _max = maxJ - minJ
    let H; let S; let V
    if (r1 == r2 && r2 == r3) {
        H = 0
        S = 0
    } else {
        switch (maxJ) {
            case r1:
                H = (r2 - r3) / _max
                break
            case r2:
                H = 2 + (r3 - r1) / _max
                break
            case r3:
                H = 4 + (r1 - r2) / _max
                break
            default:
                break
        }
        H *= 60
        if (H < 0) H += 360
        H = (H).toFixed(2)
        S = ((maxJ - minJ) / maxJ).toFixed(2)
    }
    V = (maxJ / 255).toFixed(2)
    return [H, S, V]
}

const hex2rgb = (a) => {// #ffffff
    // 十六进制颜色值的正则表达式
    var sColor = a.toLowerCase();
    if (sColor && hexReg.test(sColor)) {
        if (sColor.length === 4) {
            var sColorNew = "#";
            for (var i = 1; i < 4; i += 1) {
                sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1));
            }
            sColor = sColorNew;
        }
        //处理六位的颜色值
        var sColorChange = [];
        for (var i = 1; i < 7; i += 2) {
            sColorChange.push(parseInt("0x" + sColor.slice(i, i + 2)));
        }
        return "RGB(" + sColorChange.join(",") + ")";
    } else {
        return sColor;
    }
}

const rgb2hex = (color) => {
    if (color.indexOf('#') != -1) {
        return color
    }
    const arr = color.split(',')
    const r = +arr[0].split('(')[1]
    const g = +arr[1]
    const b = +arr[2].split(')')[0]
    const value = ((1 << 24) + r * (1 << 16) + g * (1 << 8) + b).toString(16)
    return '#' + value.slice(1).toUpperCase()
}